<?php

// +----------------------------------------------------------------------
// | POS机回调
// +----------------------------------------------------------------------
// | Copyright (c) 2015-2024 http://www.yicmf.com, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 微尘 <yicmf@qq.com>
// +----------------------------------------------------------------------

namespace app\controller\api\notify;

use app\event\pos\Pos as PosEvent;
use app\event\ucenter\User as UserEvent;
use app\model\pos\Pos as PosModel;
use app\model\pos\PosTrade as PosTradeModel;
use app\model\pos\Store as StoreModel;
use app\event\pos\PosTrade as PosTradeEvent;
use app\model\ucenter\User as UserModel;
use app\model\ucenter\UserMoneyLog;
use think\Exception;
use think\facade\Db;
use think\facade\Log;
use yicmf\tools\Rsa;

class La extends Common
{

    /**
     * @return array|false|mixed
     * 卡种    卡种名称
     * 00    借记卡
     * 01    贷记卡
     * 03    预付卡
     * 04    未知卡种
     * 50    外卡
     * 53    JCB
     * 54    VISA
     * 55    MASTER
     * 56    AMEX
     * 57    DINERS
     * 60    境外借记卡
     * 61    境外贷记卡
     * 71    华兴钱包
     * 72    applepay借记卡
     * 73    applepay贷记卡
     * 74    数币钱包
     * 79    储值卡
     * 81    银联二维码借记卡
     * 82    银联二维码贷记卡
     * 85    建行钱包
     * 86    QQ钱包
     * 87    翼支付钱包
     * 88    微信刷脸
     * 89    支付宝刷脸
     * 91    微信钱包
     * 92    支付宝钱包
     * 93    百度钱包
     * 94    银联扫码付
     * 95    京东钱包
     * 96    拉卡拉钱包
     * 97    积分购钱包
     * 98    苏宁钱包
     * 22    银联刷脸借记
     * 21    银联刷脸贷记
     * 89    支付宝刷脸
     * 88    微信刷脸
     */
    private function _getData()
    {
        $data = $this->request->param();
        file_put_contents($this->request->action() . '_la.txt', json_encode($data) . "\r\n\r\n", FILE_APPEND);
//        $data = '{"data":"FPfJRH4CHQ0L8BW3R2+EIBUccna727wmq\/4eT0wCyt+IcHSmvn99IlYGc3mUtsznyU8m43kjC3hTeUOQ3HLN0SkFkoM9sxoME5Gq17moyELp1GZFuQYZJFHMyI+WsSzFsSQzEPpMcEGIaN73tnzVc+JhY+P3kScC0GJJiIu1Wc10Tyj\/L8UewzkWr5qJaJzQ73q6R3OmggWyVkUJDhEMYd+7NPLk+RjpODp07Xbc4jtWU3vmW2eiCVqEEJrhE4S+9+607xQ1dWEvWk45FWGUKtJhTIWN0Obiai5U8yUyWHSrEMe8\/EfsHogbMbhTGkgh3GJc461JrjRGe1IsJQHvcHRcfWXFEvrnsbMNDVL5zZAGK\/P\/4+wsi2reK8srMy\/e0e9By3MdkT+0UZMLbxETyff\/LNVn3al0eAYAPN68\/JVekdUopvTzQLarJswwx1lj84RxpOuAtfFf4ZRko+0qmVH00OzkHdmS4F\/IPzuQrv7ApURLoMT1Fr1nxdWrxR8f","id":"119364425211123","controller":"la","action":"trade"}';
//        $data = json_decode($data, true);
        Log::write($data);
        if (isset($data['id'])) {
            return $this->checkRsa($data);
        } else {
            return false;
        }
    }

    /**
     * 终端事件
     *
     * 参数名称    参数说明    是否必须    数据类型    描述
     * posSn    机具SN    true    string
     * posType    机具类型    true    string    见附录:终端类型
     * posModel    机具型号    true    string
     * eventType    事件类型    true    string    ADD:新增,结构见16.2[终端事件-新增]
     * DEL:删除,结构见16.3[终端事件-删除]
     * ASSIGN:划拨,结构见16.4[终端事件-划拨]
     * RETURN:回调,结构见16.5[终端事件-回调]
     * ACTIVE:激活,结构见16.6[终端事件-激活]
     * CHANGE_ACTIVITY:变更活动,结构见16.7[终端事件-变更活动]
     * eventTime    事件时间    true    string    yyyy-MM-dd HH:mm:ss
     * expand    拓展信息    true    object    参阅eventType
     */
    public function pos()
    {
        $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        return json($rep);
    }


    /**
     * 机具绑定回调
     * 参数名称    参数说明    是否必须    数据类型    描述
     * orgCode    机构编号    true    string
     * agentNo    合作方编号    true    string
     * agencyNo    服务商编号    true    string
     * externalCustomerNo    外部商户编号    true    string
     * customerName    商户名称    true    string    脱敏[前2后2]
     * legalName    法人姓名    true    string    脱敏[前1后1]
     * posSn    机具SN    true    string
     * posType    机具类型    true    string    附录:终端类型
     * termNo    终端号    true    string
     * type    事件类型    true    string    BIND:绑定,UNBIND:解绑
     * operateTime    操作时间    true    string    yyyy-MM-dd HH:mm:ss
     */
    public function bind()
    {

        $data = $this->_getData();
        if ($data) {
            try {
                if ($data['type'] == 'UNBIND') {
                    throw new Exception('解绑');
                }
                Db::startTrans();
                //POS机处理
                $pos = PosModel::where('sn', $data['posSn'])->where('channel_id', 1)->find();
                if (!$pos) {
                    throw new Exception('无pos');
                    // 新增无主pos机
//                    $insert = [];
//                    $insert['name'] = '拉卡拉';
//                    $insert['channel_id'] = 1;
//                    $insert['sn'] = $data['posSn'];
//                    $pos = PosModel::create($insert);
                }
                $store = StoreModel::where('store_sn', $data['externalCustomerNo'])->find();
                if (!$store) {
                    $store['channel_id'] = 1;
                    $store['mobile'] = isset($data['phone'])?$data['phone']:'';
                    $store['store_sn'] = $data['externalCustomerNo'];
                    $store['nickname'] = $data['customerName'];
                    $store['pos_sn'] = $data['posSn'];
                    $store['contacts'] = $data['legalName'];
                    $store['user_id'] = $pos['user_id'];
                    $store = StoreModel::create($store);
                }
                $pos['store_id'] = $store['id'];
                $pos['term_no'] = $data['termNo'];
                $pos['bind_time'] = $data['operateTime'];
                $pos['model'] = $data['posType'];
                if (!$pos->save()) {
                    throw new Exception('资料保存异常');
                }
                Db::commit();
                $rep = ['ret_code' => '00', 'ret_msg' => 'SUCCESS'];
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $rep = ['ret_code' => '01', 'ret_msg' => $e->getMessage()];
            }
        } else {
            $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        }
        return json($rep);
    }


    /**
     * 流量费
     * 参数名称    参数说明    是否必须    数据类型    描述
     * logNo    流水号    true    string
     * posSn    机具SN    true    string
     * externalCustomerNo    商户编号    true    string
     * amount    扣款金额    true    string    单位:元,2位小数
     * time    应扣时间    true    string    yyyy-MM-dd HH:mm:ss
     * deductDate    扣费日期    false    string    yyyyMMdd
     * agencyNo    服务商编号    true    string
     */
    public function flow()
    {
        $data = $this->_getData();
        if ($data) {
            try {
//                Db::startTrans();
                //POS机处理
                $pos = PosModel::where('sn', $data['posSn'])->where('channel_id', 1)->find();
                if (!$pos) {
                    // 新增无主pos机
                    throw new Exception('无pos');
//                    $insert = [];
//                    $insert['name'] = '拉卡拉绑定';
//                    $insert['sn'] = $data['posSn'];
//                    $insert['channel_id'] = 1;
//                    $pos = PosModel::create($insert);
                }

                $event = new PosEvent();
                $re = $event->flow($pos,$data['logNo'],1);
                if ($re['code'] != 0) {
                    throw new Exception($re['message']);
                }
//                $pos['merch_no'] = $data['externalCustomerNo'];
//                if (!$pos->save()) {
//                    throw new Exception('资料保存异常');
//                }
//                if ($pos['cashback_user_id'] || $pos['buy_user_id']) {
//                    //参加返现
//                    if ($pos['cashback_user_id'])
//                    {
//                        $user = UserModel::where('id', $pos['cashback_user_id'])->find();
//                    }else{
//                        $user = UserModel::where('id', $pos['buy_user_id'])->find();
//                    }
//                    if ($user) {
//                        // 流量费返现
//                        $log = UserMoneyLog::where('order_id', $data['logNo'])->where('type',91)->where('channel', 1)->where('user_id', $user['id'])->find();
//                        if (!$log) {
//                            //参加返现
//                            $amount = 40;
////                            $user['my_balance'] = $user['my_balance'] + $data['amount'] / 100;
//                            $user['my_balance'] = $user['my_balance'] + $amount;
//                            $user->save();
//                            UserEvent::money($amount, $user['id'], '流量返现（' . $pos['sn'] . '）', 91, $pos['user_id'], $data['logNo'], 0, 1,16);
//                        }
//                    }
//
//                }
//                Db::commit();

                $rep = ['ret_code' => '00', 'ret_msg' => 'SUCCESS'];
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $rep = ['ret_code' => '01', 'ret_msg' => $e->getMessage()];
            }
        } else {
            $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        }
        return json($rep);
    }

    public function test()
    {
        $s = 'IC0zYAaJUfB05JcWewM+zOESvrg1JhASyUCDEHX4pgf1xVt3sGezrzK22GkNGyStcPkH2hjntt8DJm0ry9iIAgig0LlFQWD4IfTq56EY7jEWvsv5kZ78Tf+Sfc6rQrLEnX7vEDbQFMbaFepFBoXRjv1o3bB1IPAlywUuFzh8yRNs628ylDylGYWDm7ED85zL4sbfZVuwuMLnw4YqV4P0pPK/2nLpEzKeMF3Kol9zAq2pT9VVJU1gfoD7f9neAme+pBKciUA8AvyvMT0cFSs3RM5b7LnO6fz9TxU3N4y6H9okvdze5SztorG69hfdF0+YBhl43Ga3gYSIXLwid1zrfx48Aj+G9ABHMOvu0kU4L5W016SLbcRjiXmgZPsWOMDuUI52DtxN/A6doZgnLHl7oZ/dd/lGLjamQnEQZ5UG1jfM+Rm1Zher8A87brA/7iPzyM7l3Lff3l8p4UzUEtP2F533muOLMwe7OtsxFFVKSiZPPVhOP4FHPM0SKwQ90FLye/LhXdlKIHi4m1Nos7y+z8bd9KZKEaVGE964AD7Jtfs5zhzZzajJXPcBhg7wb/sIHHXtwebfw0j90ItVULg/s3jU1nHfj9A9Qonnzuht3rX/YGsuivo3dHsRW18Iuqi6MQ6rPss5HL96YxfiZJQkTs6qZoXFUpvHgWL9I8BRzGQ=';
        $s = 'KbtdTs60yIE8U2c\/BjkrzOQCiDi\/kZYqQgYfKdN4NPBrJmQXU96qBMGL9bsJKnFq3Vnr6BF9t6vFBvz1SV+V49Hmg0BbfSfdYaesrLBeaDTJ0R18RVpNJCLzoYF4vcDx6iQYpaX11hke11L\/xds5UbO8neLnJyWdO4XF+yndE8li7KHDkveTh7K102vcrVLDPp\/Hhn6\/rg3PFftf9XdYWLbJMqey\/zblTXxqdhQZX\/h67CX8IxM+Nqad1EycwqmdHcQdjmnzCeClT00mWhoKJLeNaP18YWG+xvOXmfR4A49al1Sduy77m498WTfzJVCnCxNVeXU7XfJEYd8tPq9Mgg==';

        $rsa = new Rsa($this->test_pri_key, $this->test_pub_key);
        $re = $rsa->publicDecrypt($s);
        dump(json_decode($re,true));

    }

    /**
     * 交易流水通知
     * 参数名称    参数说明    是否必须    数据类型    描述
     * orderNo    流⽔号    true    string
     * userNo    合作方编号    true    string
     * agencyNo    服务商编号    true    string
     * customerNo    内部商户编号    true    string    拓客内部编号
     * externalCustomerNo    外部商户编号    true    string    822开头编号
     * customerName    商户名称    true    string    脱敏[前2后2]
     * legalName    法人名称    true    string    脱敏[前1后1]
     * posSn    机具编号    true    string
     * type    交易类型    true    string    TRANS:正常交易
     * DEPOSIT:押金类型
     * transCardType    卡类型    true    string    参考附录:交易卡类型
     * extTransCode    交易码    true    string    参考附录:交易码类型
     * termId    终端号    true    string
     * cardNo    卡号    false    string    脱敏[前6后4]
     * srefNo    系统参考号    false    string
     * ologNo    原交易流水号    false    string
     * amount    交易金额    true    string    单位:分
     * transTime    交易时间    true    string    yyyy-MM-dd HH:mm:ss
     */
    public function trade()
    {
        $data = $this->_getData();
        if ($data) {
            try {
                $trade = PosTradeModel::where('channel_id', 1)->where('order_sn', $data['orderNo'])->find();
                if ($trade) {
                    throw new Exception('已经处理');
                }
                $insert = [];
                $insert['order_sn'] = $data['orderNo'];
                $insert['pos_sn'] = $data['posSn'];
                $insert['refer_no'] = $data['srefNo'];
                $insert['trans_sn'] = $data['orderNo'];
//                $insert['trans_sn'] = $data['ologNo'];
                $insert['amount'] = round((float)$data['amount'] / 100, 2);
                $insert['trans_time'] = $data['transTime'];
                $insert['busi_type'] = $data['type'];//参考附录:交易卡类
                $insert['busi_sub_type'] = $data['extTransCode'];//参考附录:交易码类型
                $insert['term_no'] = $data['termId'];
                $insert['merch_no'] = $data['externalCustomerNo'];
                $insert['card_no'] = isset($data['cardNo']) ? $data['cardNo'] : '';
                $insert['pay_type'] = $data['transCardType'];
                if (in_array($insert['pay_type'], ['00', '72'])) {
                    $insert['card_type'] = 1;
                } else {
                    $insert['card_type'] = 2;
                }
                if (in_array($insert['pay_type'], ['00', '01', '81', '82', '94', '72', '73'])) {
                    $insert['trade_type'] = 1;
                } elseif (in_array($insert['pay_type'], ['88', '89', '91', '92'])) {
                    $insert['trade_type'] = 2;
                } else {
                    $insert['trade_type'] = 3;
                }

                $insert['type'] = 1;
                $insert['channel_id'] = 1;
                $insert['channel'] = 'la';
                $insert['status'] = 1;
                // pos机查询
                $pos = PosModel::where('sn', $insert['pos_sn'])->where('status', 1)->find();
                if ($pos) {
                    $insert['pos_id'] = $pos['id'];
                    $insert['user_id'] = $pos['user_id'];
                    if ($pos['store_id'])
                    {
                        $insert['store_id'] = $pos['store_id'];
                    }else{
                        // 新增商户信息
                        $store['nickname'] = $data['customerName'];
                        $store['store_sn'] = $data['externalCustomerNo'];
                        $store['contacts'] = $data['legalName'];
                        $store['pos_sn'] = $data['posSn'];
                        $store['channel_id'] = 1;
                        $store['channel'] = 'la';
                        $store = StoreModel::create($store);
                        $pos['store_id'] = $store['id'];
                        $pos->save();
                        $insert['store_id'] = $pos['store_id'];
                    }
                    $insert['agent_id'] = $pos['agent_id'];
                }else{
                    throw new Exception('未知');
                }
                $trade = PosTradeModel::create($insert);
                if (!$trade) {
                    throw new Exception('数据异常');
                }
                if ($insert['trade_type'] == 1 || $insert['trade_type'] == 2) {
                    $event = new PosTradeEvent();
                    $re = $event->trade($trade,$pos);
                    if ($re['code'] != 0)
                    {
                        throw new Exception($re['message']);
                    }
                }
                $rep = ['ret_code' => '00', 'ret_msg' => 'SUCCESS'];
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $rep = ['ret_code' => '01', 'ret_msg' => $e->getMessage()];
            }
        } else {
            $rep = ['ret_code' => '01', 'ret_msg' => 'FAIL'];
        }
        return json($rep);
    }

    /**
     * 私钥加密
     * @param $data
     * @return string
     */
    public static function privateKeyDecrypt($data, $privateKey)
    {
        $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" .
            wordwrap($privateKey, 64, "\n", true) .
            "\n-----END RSA PRIVATE KEY-----";
        $crypto = '';
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $privateKey);
            $crypto .= $encryptData;
        }
        $encrypted = base64_encode($crypto);
        return $encrypted;
    }

    /**
     * 公钥解密
     * @param $data
     * @return string
     */
    public static function publicKeyDecrypt($data, $pubKey)
    {
        $pubKey = "-----BEGIN PUBLIC KEY-----\n" .
            wordwrap($pubKey, 64, "\n", true)
            . "\n-----END PUBLIC KEY-----";
        $crypto = '';
        foreach (str_split(base64_decode($data), 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pubKey);
            $crypto .= $decryptData;
        }
        return $crypto;
    }

    /**
     * 校验
     * @return void
     */
    protected function checkRsa($data)
    {
        $rsa = new Rsa($this->test_pri_key, $this->test_pub_key);
        $re = $rsa->publicDecrypt($data['data']);
        file_put_contents($this->request->action() . '_la.txt', $re. "\r\n\r\n", FILE_APPEND);
        $json = json_decode($re, true);
        if (is_array($json)) {
            return $json;
        } else {
            return false;
        }
    }


    /**
     * 加签
     *
     * @param string $privateKey RSA私钥
     * @param string $data 加签数据
     * @return string 签名的Base64编码
     */
    protected function sign($privateKey, $data)
    {
        $privateKeyId = openssl_pkey_get_private($privateKey);
        openssl_sign($data, $signature, $privateKeyId, OPENSSL_ALGO_SHA256);
        return base64_encode($signature);
    }

    /**
     * 验证数字签名
     *
     * @param string $publicKey RSA公钥
     * @param string $data 原文
     * @param string $signature 签名的Base64编码
     * @return bool 验证是否成功
     */
    protected function verify($publicKey, $data, $signature)
    {
        $publicKeyId = openssl_pkey_get_public($publicKey);
        $result = openssl_verify($data, base64_decode($signature), $publicKeyId, OPENSSL_ALGO_SHA256);
        return $result === 1;
    }

    /**
     * 使用sha256算法进行数据摘要
     *
     * @param string $data 摘要原文
     * @return string 摘要的Hex编码
     */
    protected function sha256($data)
    {
        return hash('sha256', $data, false);
    }

    protected $test_pri_key = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALZTEriMSN454ITeo/MDAvJiAKD6RiqXu4eq2yHnHzBpNf+QkpTcIUqwxHspKkUZGF9aOojzUsezrSMV/YdfQEb/xRsLZO85ZLyUo8lKcM+qfmzyx2+B3SMLUkfWrbuao8WVjwyxEheUR7rVmY4gJWcCYwemNDgpCri2iuOlEMZTAgMBAAECgYAZVXpgyaAHvj5emAUV65GJlmkvSmIHjGUoA8Cbzwk8E9Jx/BJcvChQFYx87zUKvDhGajt/SLge5u4kKuu7LKwPNPEeCik1mNdcbrHl9YGDnYK86+46HN8UAExG5g4rfCQBxDl8IgVKK8aTfZikboxoBTq8tI8BR8DZH/QrYlFQmQJBAPYpjbn1hUU4n20JnAc4y+1l8woHSk00sJg/VLWu6VaJf2VxnFZWvRqkSyjfGTAZvFvPBPxGr7aJCNkkNeigNUcCQQC9nGfAkyuP0msnx8Z7ZINSKkvvpxPKw1EPbUTewGMx6NYsM0gOJsPgLjNQEQOG/C3yBQh3ILFKuVy0cUutEhyVAkEAv6pTI7u7bM5Ns8SLrEPY5JtAxUov3DVuWtzUxDHQlQSyIPZ41/DphNjvfH9ZSU6Ajqt+Ij+XiPTh4tCC+QHk+QJAbquXs0MzLeL3QGTOaL8mFxMw91RhrPuLmKGCjTFltH/eYjYcXIYr1fGhaZ5EnMkcWCKv6jhewuqmPXvTW9UycQJAHE3qxreOqLLrvVBoOkkxNYzsVHBUOO1/oPA3yDiwxhlKEGgzOZFf5j24vCF+GrFPg7ssPfj+VO8HraopDMbhjw==';
    protected $test_pub_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2UxK4jEjeOeCE3qPzAwLyYgCg+kYql7uHqtsh5x8waTX/kJKU3CFKsMR7KSpFGRhfWjqI81LHs60jFf2HX0BG/8UbC2TvOWS8lKPJSnDPqn5s8sdvgd0jC1JH1q27mqPFlY8MsRIXlEe61ZmOICVnAmMHpjQ4KQq4torjpRDGUwIDAQAB';
}
